package com.atguigu.ssyx.activity.service.impl;


import com.atguigu.ssyx.activity.mapper.CouponInfoMapper;
import com.atguigu.ssyx.activity.mapper.CouponRangeMapper;
import com.atguigu.ssyx.activity.mapper.CouponUseMapper;
import com.atguigu.ssyx.activity.service.CouponInfoService;
import com.atguigu.ssyx.client.product.ProductFeignClient;
import com.atguigu.ssyx.enums.CouponRangeType;
import com.atguigu.ssyx.enums.CouponStatus;
import com.atguigu.ssyx.model.activity.CouponInfo;
import com.atguigu.ssyx.model.activity.CouponRange;
import com.atguigu.ssyx.model.activity.CouponUse;
import com.atguigu.ssyx.model.order.CartInfo;
import com.atguigu.ssyx.model.product.Category;
import com.atguigu.ssyx.model.product.SkuInfo;
import com.atguigu.ssyx.vo.activity.CouponRuleVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Maps;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 优惠券信息 服务实现类
 * </p>
 *
 * @author atguigu
 * @since 2025-09-17
 */
@Service
public class CouponInfoServiceImpl extends ServiceImpl<CouponInfoMapper, CouponInfo> implements CouponInfoService {

    @Autowired
    private CouponRangeMapper couponRangeMapper;

    @Autowired
    private ProductFeignClient productFeignClient;

    @Autowired
    private CouponUseMapper couponUseMapper;

    //1.优惠劵的分页查询
    @Override
    public IPage<CouponInfo> selectPage(Page<CouponInfo> pagegaram) {
        IPage<CouponInfo> couponInfoPage = baseMapper.selectPage(pagegaram, null);
        List<CouponInfo> couponInfoList = couponInfoPage.getRecords();
        couponInfoList.stream().forEach(item -> {
           item.setCouponTypeString(item.getCouponType().getComment());
            CouponRangeType rangeType = item.getRangeType();
            if (rangeType != null) {
                item.setRangeTypeString(rangeType.getComment());
            }
        });
        return couponInfoPage;
    }
    //3.根据id查询优惠劵
    @Override
    public CouponInfo getCouponInfoById(Long id) {
        CouponInfo couponInfo = baseMapper.selectById(id);
        couponInfo.setCouponTypeString(couponInfo.getCouponType().getComment());
        if (couponInfo.getRangeType() != null) {
            couponInfo.setRangeTypeString(couponInfo.getRangeType().getComment());
        }
        return couponInfo;
    }

    @Override
    public Map<String, Object> findCouponRuleList(Long id) {
        //根据优惠劵id查询优惠劵的信息coupon_info
        CouponInfo couponInfo = baseMapper.selectById(id);
        //根据优惠劵id查询coupon_range里面对应的range_id的值
        List<CouponRange> couponRangeList = couponRangeMapper.selectList(
                new LambdaQueryWrapper<CouponRange>().eq(CouponRange::getCouponId, id)
        );

        List<Long> rangeIdList = couponRangeList.stream().map(CouponRange::getRangeId).collect(Collectors.toList());
        Map<String, Object> reultMap = new HashMap<>();
        if (!CollectionUtils.isEmpty(rangeIdList)) {
            //分别判断封装不同的数据
            //如果规则类型是SKU,range_id就是skuId的值
            if(couponInfo.getRangeType()==CouponRangeType.SKU){
                //如果规则类型是sku 得到skuid 远程调用根据多个skuid的值获取对应的sku信息
                List<SkuInfo> skuInfoList = productFeignClient.findSkuInfoList(rangeIdList);
                reultMap.put("skuInfoList", skuInfoList);

            }
            //如果规则类型是Category range_id就是分类id的值
            else if (couponInfo.getRangeType()==CouponRangeType.CATEGORY) {

                //如果规则类型是分类 得到分类id  远程调用根据多个分类id的值获取对应的分类信息
              List<Category> categoryList = productFeignClient.findCategoryList(rangeIdList);
              reultMap.put("categoryList", categoryList);
            }

        }
        return reultMap;
    }

    @Override
    public void saveCouponRule(CouponRuleVo couponRuleVo) {
        //先根据优惠劵id删除规则数据
        couponRangeMapper.delete(
                new LambdaQueryWrapper<CouponRange>().eq(CouponRange::getCouponId,couponRuleVo.getCouponId())
        );
        //更新优惠劵基本信息
        CouponInfo couponInfo = baseMapper.selectById(couponRuleVo.getCouponId());
        // couponInfo.setCouponType();
        couponInfo.setRangeType(couponRuleVo.getRangeType());
        couponInfo.setConditionAmount(couponRuleVo.getConditionAmount());
        couponInfo.setAmount(couponRuleVo.getAmount());
        couponInfo.setConditionAmount(couponRuleVo.getConditionAmount());
        couponInfo.setRangeDesc(couponRuleVo.getRangeDesc());

        baseMapper.updateById(couponInfo);

        //添加新的优惠劵规则数据
        List<CouponRange> couponRangeList = couponRuleVo.getCouponRangeList();
        
        // 去重处理：根据rangeId去重，避免重复添加相同的商品
        Map<Long, CouponRange> uniqueRangeMap = new HashMap<>();
        for (CouponRange couponRange : couponRangeList) {
            if (couponRange.getRangeId() != null) {
                uniqueRangeMap.put(couponRange.getRangeId(), couponRange);
            }
        }
        
        // 插入去重后的数据
        for (CouponRange couponRange : uniqueRangeMap.values()) {
            //设置优惠劵id
            couponRange.setCouponId(couponRuleVo.getCouponId());
            //添加
            couponRangeMapper.insert(couponRange);
        }
    }

    @Override
    public List<CouponInfo> findCouponByKeyword(String keyword) {
        // 第一步：根据关键字查询优惠券匹配的内容列表
        LambdaQueryWrapper<CouponInfo> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.like(CouponInfo::getCouponName, keyword)
                .or()
                .like(CouponInfo::getRangeDesc, keyword)
                .eq(CouponInfo::getIsDeleted, 1); // 只查询未删除的优惠券

        List<CouponInfo> couponInfoList = baseMapper.selectList(queryWrapper);

        if (CollectionUtils.isEmpty(couponInfoList)) {
            return Collections.emptyList();
        }

        // 第二步：为每个优惠券设置类型和范围类型的字符串描述
        couponInfoList.forEach(couponInfo -> {
            couponInfo.setCouponTypeString(couponInfo.getCouponType().getComment());
            if (couponInfo.getRangeType() != null) {
                couponInfo.setRangeTypeString(couponInfo.getRangeType().getComment());
            }
        });

        return couponInfoList;
    }
    //根据skuid和userid查询优惠卷信息
    @Override
    public List<CouponInfo> findCouponInfoList(Long skuId, Long userId) {
        //根据skuid获取skuinfo信息
        SkuInfo skuInfo = productFeignClient.getSkuInfo(skuId);
        //根据条件查询：skuid+分类id+userid
        List<CouponInfo> couponInfoList=baseMapper.selectCouponInfoList(skuInfo.getId(),skuInfo.getCategoryId(),userId);
        return couponInfoList;
    }

    @Override
    public List<CouponInfo> findCartCouponInfo(List<CartInfo> cartInfoList, Long userId) {
        //1.根据用户id获取到全部的优惠劵
        //coupon_use coupon_info
        List<CouponInfo> userAllCouponInfoList= baseMapper.selectCartCouponInfoList(userId);
        if(CollectionUtils.isEmpty(userAllCouponInfoList)){
            return new ArrayList<CouponInfo>();
        }
        //2.从第一步返回list集合中,获取所有优惠卷id列表
        List<Long> couponInfoIdList = userAllCouponInfoList.stream().map(couponInfo -> couponInfo.getId()).collect(Collectors.toList());
        //3.查询优惠卷对应的范围coupon_range
        //couponRangeList
        LambdaQueryWrapper<CouponRange> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.in(CouponRange::getCouponId, couponInfoIdList);
        List<CouponRange> couponRangeList = couponRangeMapper.selectList(queryWrapper);

        //4 获取优惠卷id 对象skuId列表
        //优惠卷id进行分组,得到map集合
        //Map<Long,List<Long>>
        Map<Long,List<Long>> couponIdToSkuIdMap
        =this.findCouponIdToSkuIdMap(cartInfoList,couponRangeList);
        //5 遍历全部优惠劵集合，判断优惠卷类型
        //全场通用，sku 分类
        BigDecimal reduceAmount = new BigDecimal(0) ;
        CouponInfo optimalCouponInfo = null;
        for(CouponInfo couponInfo :userAllCouponInfoList){
            //全场通用
            if(CouponRangeType.ALL == couponInfo.getRangeType()){
                //计算优惠的金额
                //全场通用
                //判断是否满足优惠使用门槛
                //计算购物车商品的总价
                BigDecimal totalAmount = computeTotalAmount(cartInfoList);
                if(totalAmount.subtract(couponInfo.getConditionAmount()).doubleValue() >= 0){
                    couponInfo.setIsSelect(1);
                }
            }else {
                //优惠劵id获取对应的skuid列表
                List<Long> skuIdList = couponIdToSkuIdMap.get(couponInfo.getId());
                //满足使用范围购物项
                List<CartInfo> currentCartInfoList = cartInfoList.stream().filter(
                        cartInfo -> skuIdList.contains(cartInfo.getSkuId())
                ).collect(Collectors.toList());
                BigDecimal totalAmount = computeTotalAmount(currentCartInfoList);
                if(totalAmount.subtract(couponInfo.getConditionAmount()).doubleValue() >= 0){
                    couponInfo.setIsSelect(1);
                }
            }
            if (couponInfo.getIsSelect().intValue() == 1 && couponInfo.getAmount().subtract(reduceAmount).doubleValue() > 0) {
                reduceAmount = couponInfo.getAmount();
                optimalCouponInfo = couponInfo;
            }
        }
        //最终返回List<CouponInfo>
        if(null != optimalCouponInfo) {
            optimalCouponInfo.setIsOptimal(1);
        }
        return userAllCouponInfoList;
    }
    //获取购物车对应的优惠卷
    @Override
    public CouponInfo findRangeSkuIdList(List<CartInfo> cartInfoList, Long couponId) {
        //根据优惠卷id查询基本信息
        CouponInfo couponInfo = baseMapper.selectById(couponId);
        if(null == couponInfo){
            return null;
        }
        //根据优惠卷id查询对应的Couponrange数据
        List<CouponRange> couponRangeList = couponRangeMapper.selectList(
                new LambdaQueryWrapper<CouponRange>()
                        .eq(CouponRange::getCouponId, couponId)
        );
        //查询对应skuid信息
        Map<Long, List<Long>> couponIdToSkuIdMap = this.findCouponIdToSkuIdMap(cartInfoList, couponRangeList);
        //遍历map得到value值 封装couponInfo对象

        List<Long> skuIdList = couponIdToSkuIdMap.entrySet().iterator().next().getValue();
        couponInfo.setSkuIdList(skuIdList);
        return couponInfo;
    }
    //更新优惠卷状态
    @Override
    public void updateCouponInfoUseStatus(Long couponId, Long userId, Long orderId) {
        //根据couponId查询优惠卷信息
        CouponUse couponUse = couponUseMapper.selectOne(
                new LambdaQueryWrapper<CouponUse>()
                        .eq(CouponUse::getCouponId, couponId)
                        .eq(CouponUse::getUserId, userId)
                        .eq(CouponUse::getOrderId, orderId)
        );
        //设置修改值
        couponUse.setCouponStatus(CouponStatus.USED);
        //调用方法修改
        couponUseMapper.updateById(couponUse);
    }

    private BigDecimal computeTotalAmount(List<CartInfo> cartInfoList) {
        BigDecimal total = new BigDecimal("0");
        for (CartInfo cartInfo : cartInfoList) {
            //是否选中
            if(cartInfo.getIsChecked().intValue() == 1) {
                BigDecimal itemTotal = cartInfo.getCartPrice().multiply(new BigDecimal(cartInfo.getSkuNum()));
                total = total.add(itemTotal);
            }
        }
        return total;
    }
    //4 获取优惠卷id 对象skuId列表
    //优惠卷id进行分组,得到map集合
    private Map<Long, List<Long>> findCouponIdToSkuIdMap(List<CartInfo> cartInfoList, List<CouponRange> couponRangeList) {
        Map<Long, List<Long>> couponIdToSkuIdMap = new HashMap<>();
        //couponRangeList数据处理，根据优惠劵id分组
        Map<Long, List<CouponRange>> couponRangeToRangeListMap = couponRangeList.stream().collect(
                Collectors.groupingBy(couponRange -> couponRange.getCouponId())
        );
        Iterator<Map.Entry<Long, List<CouponRange>>> iterator =
                couponRangeToRangeListMap.entrySet().iterator();
        while (iterator.hasNext()) {
            Map.Entry<Long, List<CouponRange>> entry = iterator.next();
            Long couponId = entry.getKey();
            List<CouponRange> rangeList = entry.getValue();
            //创建集合set
            Set<Long> skuIdSet = new HashSet<>();
            for (CartInfo cartInfo : cartInfoList) {
                for (CouponRange couponRange : rangeList) {
                    //判断
                    if(couponRange.getRangeType() == CouponRangeType.SKU
                    && couponRange.getRangeId().longValue() ==  cartInfo.getSkuId().longValue()){
                        skuIdSet.add(cartInfo.getSkuId());
                    }else if(couponRange.getRangeType() == CouponRangeType.CATEGORY
                    && couponRange.getRangeId().longValue() == cartInfo.getCategoryId().longValue()){
                        skuIdSet.add(cartInfo.getSkuId());
                    }else{

                    }
                }
            }

            couponIdToSkuIdMap.put(couponId,new ArrayList<>(skuIdSet));
        }
        return couponIdToSkuIdMap;
    }
}
